package com.lagou.edu.factory;

import com.lagou.edu.annotation.Autowired;
import com.lagou.edu.annotation.Repository;
import com.lagou.edu.annotation.Transactional;
import com.lagou.edu.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author 刘强
 * <p>
 * <p>
 * 代理对象工厂：生成代理对象的
 */
@Repository
public class ProxyFactory {
    @Autowired
    private TransactionManager transactionManager;

    public void setTransactionManager(TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    /**
     * 动态代理
     *
     * @param obj
     * @return
     */
    public Object getProxy(Object obj) {
        Object rstObj = null;
        Class<?>[] interfaces = obj.getClass().getInterfaces();
        if (interfaces == null || interfaces.length == 0) {
            rstObj = getCglibProxy(obj);
        } else {
            rstObj = getJdkProxy(obj);
        }
        return rstObj;
    }

    /**
     * Jdk动态代理
     *
     * @param obj 委托对象
     * @return 代理对象
     */
    public Object getJdkProxy(Object obj) {
        // 获取代理对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        return commonInvoke(obj, method, args);
                    }
                });
    }

    /**
     * 使用cglib动态代理生成代理对象
     *
     * @param obj 委托对象
     * @return
     */
    public Object getCglibProxy(Object obj) {
        return Enhancer.create(obj.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                return commonInvoke(obj, method, args);
            }
        });
    }

    // 事务处理
    private Object commonInvoke(Object obj, Method method, Object[] args) throws Throwable {
        Object result = null;
        Class<?> c = obj.getClass();
        // 是否添加事务 类上面添加，方法上面添加
        if (c.isAnnotationPresent(Transactional.class)
                || c.getMethod(method.getName(), method.getParameterTypes()).isAnnotationPresent(Transactional.class)) {
            result = transactionInvoke(obj, method, args);
        } else {
            result = method.invoke(obj, args);
        }

        return result;
    }

    // 事务处理
    private Object transactionInvoke(Object obj, Method method, Object[] args) throws Throwable {
        Object result = null;
        try {
            // 开启事务(关闭事务的自动提交)
            transactionManager.beginTransaction();
            result = method.invoke(obj, args);
            // 提交事务
            transactionManager.commit();
        } catch (Exception e) {
            e.printStackTrace();
            // 回滚事务
            transactionManager.rollback();
            // 抛出异常便于上层servlet捕获
            throw e;
        }

        return result;
    }

}
